home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-14 | 8.6 KB | 273 lines | [TEXT/QED1] |
- // Copyright 1990 Waldemar Horwat.
- // Permission is granted for noncommercial use of this code.
-
- #include <Types.h>
- #include <Memory.h>
- #include <OSUtils.h>
- #include <String.h>
- #include <Errors.h>
- #include "HString.h"
-
-
- OSErr String::err=0;
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Copy src to this without deallocating whatever was in this previously. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- void String::internalCopy(const String &src)
- {
- if (data=src.data) data->refCount++;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Copy cString to this without deallocating whatever was in this previously. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::internalCopy(const char *cString)
- {
- int length=strlen(cString);
-
- if (data=(StringData *)NewHandle(length+5))
- {
- data->refCount=1;
- BlockMove(Ptr(cString),data->str,length+1);
- return 0;
- }
- return String::err=memFullErr;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Make sure that this String's data is not shared with any other String. This */
- /* function should be called before this String's data is altered. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::fresh()
- {
- OSErr err;
-
- if (!data || data->refCount<=1) return 0;
- StringData *data2=data;
- if (err=HandToHand((Handle *)&data2)) return String::err=err;
- data->refCount--;
- data2->refCount=1;
- data=data2;
- return 0;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Deallocate this String. Deallocate the data too if its reference count reaches */
- /* zero. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- String::~String()
- {
- if (data && !(--data->refCount))
- DisposHandle(Handle(data));
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Clear this String to a null string. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- void String::clear()
- {
- this->String::~String();
- data=0;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Assign src to this. Deallocate the old String in this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- String &String::operator=(const String &src)
- {
- if (this!=&src) //Handle a String assigned to itself correctly!
- {
- this->String::~String();
- internalCopy(src);
- }
- return *this;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Assign the cString to this. Deallocate the old String in this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator=(const char *cString)
- {
- this->String::~String();
- return internalCopy(cString);
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Return the length of this String. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- int String::length() const
- {
- if (!data) return 0;
- return strlen(data->str);
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Return the character at position index in this String. Return the null character if */
- /* index is out of bounds. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- char String::operator[](int index) const
- {
- if (!data || index<0 || index>=strlen(data->str)) return 0;
- return data->str[index];
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Return the substring of the given length starting from the given offset. The null */
- /* string is returned if the offset is out of bounds. The String returned may be */
- /* shorter than length characters if offset+length exceeds the length of this String. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- String String::substr(int offset, int length) const
- {
- String result; //Defaults to null.
- int thisLength=String::length();
-
- if (offset>=0 && offset<thisLength)
- {
- if (offset+length>=thisLength) length=thisLength-offset;
- if (result.data=(StringData *)NewHandle(length+5))
- {
- result.data->refCount=1;
- BlockMove(data->str+offset,result.data->str,length);
- result.data->str[length]='\0';
- }
- }
- return result;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Return the contents of this String as a C string. The result may move the next time */
- /* memory is allocated! */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- char *String::cString() const
- {
- if (!data) return "";
- return data->str;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Return true if the Strings are exactly equal. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- bool String::operator==(const String &src2) const
- {
- if (!data || !src2.data)
- return length()==src2.length();
- return !strcmp(data->str,src2.data->str);
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Concatenate this and src to yield a new String. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- String String::operator|(const String &src) const
- {
- String result=*this;
- result|=src;
- return result;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Destructively concatenate src to the end of this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator|=(const String &src)
- {
- OSErr err;
-
- int srcLength=src.length();
- if (!srcLength) return 0; // Nothing to concatenate?
- if (!data)
- {
- internalCopy(src);
- return 0;
- }
- if (err=fresh()) return err;
- SetHandleSize(Handle(data),GetHandleSize(Handle(data))+srcLength);
- if (err=MemError()) return String::err=err;
- strcat(data->str,src.data->str);
- return 0;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Destructively concatenate ch to the end of this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator|=(char ch)
- {
- char cString[2];
-
- cString[0]=ch;
- cString[1]='\0';
- return *this|=cString;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Destructively concatenate cString to the end of this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator|=(char *cString)
- {
- OSErr err;
-
- int srcLength=strlen(cString);
- if (!srcLength) return 0; // Nothing to concatenate?
- if (!data)
- {
- internalCopy(cString);
- return 0;
- }
- if (err=fresh()) return err;
- SetHandleSize(Handle(data),GetHandleSize(Handle(data))+srcLength);
- if (err=MemError()) return String::err=err;
- strcat(data->str,cString);
- return 0;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Destructively concatenate ch to the beginning of this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator^=(char ch)
- {
- char cString[2];
-
- cString[0]=ch;
- cString[1]='\0';
- return *this^=cString;
- }
-
-
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- /* Destructively concatenate cString to the beginning of this. */
- /*——————————————————————————————————————————————————————————————————————————————————————*/
- OSErr String::operator^=(char *cString)
- {
- OSErr err;
-
- int srcLength=strlen(cString);
- if (!srcLength) return 0; // Nothing to concatenate?
- if (!data)
- {
- internalCopy(cString);
- return 0;
- }
- if (err=fresh()) return err;
- Size dataSize=GetHandleSize(Handle(data));
- SetHandleSize(Handle(data),dataSize+srcLength);
- if (err=MemError()) return String::err=err;
- BlockMove(data->str,data->str+srcLength,dataSize-4);
- BlockMove(cString,data->str,srcLength);
- return 0;
- }
-